package fr.toto.triseries;

import java.nio.file.Path;
import java.util.List;
import java.util.Set;

import com.kokotchy.betaSeriesAPI.api.BetaseriesApiException;
import com.kokotchy.betaSeriesAPI.api.xmlImpl.BetaSerieApi;
import com.kokotchy.betaSeriesAPI.model.Episode;
import com.kokotchy.betaSeriesAPI.model.Season;
import com.kokotchy.betaSeriesAPI.model.Show;
import com.kokotchy.betaSeriesAPI.model.Subtitle;
import com.kokotchy.betaSeriesAPI.model.SubtitleLanguage;
import com.kokotchy.betaSeriesAPI.model.Error;

import fr.toto.constantes.Constantes;

public class BetaSeriesQuery implements Constantes {

	private static int timer;

	public static synchronized void InitEpisodeSet() {
		if (Reglages.DEBUG)
			System.out.print(DEBUGMSG.getString("startEpisodeSet"));
		timer = 10000;
		boolean tryagain;
		do {
			tryagain = false;
			try {
				EpisodesSet.reset(BetaSerieApi.getMembers().getEpisodes(
						Reglages.getToken(), SubtitleLanguage.ALL, false));
			} catch (BetaseriesApiException e) {
				tryagain = tryAgain(e);
			}
		} while (tryagain);
		if (Reglages.DEBUG)
			System.out.print(DEBUGMSG.getString("processComplete"));
	}

	public static synchronized Set<Season> getShowsEpisode(String url) {
		if (Reglages.DEBUG)
			System.out.print(String.format(
					DEBUGMSG.getString("startgetShowsEpisode"), url));
		Set<Season> s = null;
		boolean tryagain;
		timer = 10000;
		do {
			tryagain = false;
			try {
				s = BetaSerieApi.getShows().getEpisodes(Reglages.getToken(),
						url);
			} catch (BetaseriesApiException e) {
				tryagain = tryAgain(e);
			}
		} while (tryagain);
		if (Reglages.DEBUG)
			System.out.print(DEBUGMSG.getString("processComplete"));
		return s;
	}

	public static synchronized void setDownloaded(Episode ep) {
		if (Reglages.DEBUG)
			System.out.print(String.format(
					DEBUGMSG.getString("startsetDownloaded"), ep.toString()));
		boolean tryagain;
		timer = 10000;
		do {
			tryagain = false;
			try {
				BetaSerieApi.getMembers().setDownloaded(Reglages.getToken(),
						ep.getShowUrl(), ep.getSeason(), ep.getEpisode());
			} catch (BetaseriesApiException e) {
				tryagain = tryAgain(e);
			}
		} while (tryagain);
		// TODO test retour
		if (Reglages.DEBUG)
			System.out.print(DEBUGMSG.getString("processComplete"));
	}

	public static synchronized void iniSeriesSet() {
		if (Reglages.DEBUG)
			System.out.print(DEBUGMSG.getString("startinitSeriesSet"));
		boolean tryagain;
		timer = 10000;
		List<Show> series = null;
		do {
			tryagain = false;
			try {
				series = BetaSerieApi.getMembers().infos(Reglages.getToken())
						.getShows();
			} catch (BetaseriesApiException e) {
				tryagain = tryAgain(e);
			}
		} while (tryagain);
		SeriesSet.addAll(series);
		if (Reglages.DEBUG)
			System.out.print(DEBUGMSG.getString("processComplete"));

	}

	public static synchronized Set<Show> search(String serie) {
		if (Reglages.DEBUG)
			System.out.print(String.format(DEBUGMSG.getString("startsearch"),
					serie));
		Set<Show> s = null;
		boolean tryagain;
		do {
			tryagain = false;
			try {
				s = BetaSerieApi.getShows().search(serie);
			} catch (BetaseriesApiException e) {
				tryagain = tryAgain(e);
			}
		} while (tryagain);
		if (Reglages.DEBUG)
			System.out.print(DEBUGMSG.getString("processComplete"));
		return s;
	}

	public static synchronized void addSerie(String url) {
		if (Reglages.DEBUG)
			System.out.print(String.format(DEBUGMSG.getString("startaddSerie"),
					url));
		boolean tryagain;
		timer = 10000;
		do {
			tryagain = false;
			try {
				BetaSerieApi.getShows().add(url, Reglages.getToken());
			} catch (BetaseriesApiException e) {
				tryagain = tryAgain(e);
			}
		} while (tryagain);
		// TODO test retour
		if (Reglages.DEBUG)
			System.out.print(DEBUGMSG.getString("processComplete"));

	}

	public static synchronized Episode getEpisode(String url, int season,
			int episode) {
		if (Reglages.DEBUG)
			System.out
					.print(String.format(DEBUGMSG.getString("startgetEpisode"),
							url, season, episode));
		Episode ep = null;
		boolean tryagain;
		timer = 10000;
		do {
			tryagain = false;
			try {
				ep = BetaSerieApi.getShows().getEpisodes(Reglages.getToken(),
						url, season, episode);
			} catch (BetaseriesApiException e) {
				tryagain = tryAgain(e);
			}
		} while (tryagain);
		if (Reglages.DEBUG)
			System.out.print(DEBUGMSG.getString("processComplete"));
		return ep;
	}

	private static boolean tryAgain(BetaseriesApiException e) {
		Set<Error> errors = e.getErrors();
		for (Error error : errors) {
			System.err.print(String.format(DEBUGMSG.getString("ApiException"),
					error.getCode(), error.getText()));
			switch (error.getCode()) {
			case 2001:
				Reglages.reConnect();
				return true;
			case 100:
			case 101:
			case 102:
			case 103:
				try {
					Thread.sleep(timer);
				} catch (InterruptedException e1) {
					return false;
				}
				timer = Math.min(600000, timer * 2);
				return true;
			case 2003:
			case 2004:
			case 4001:
				continue;
			case 3004:
				return false;
			default:
				e.printStackTrace();
			}
		}
		return false;

	}

	public static synchronized Set<Subtitle> getSubtitle(String url,
			int season, int episode, SubtitleLanguage lang) {
		if (Reglages.DEBUG)
			System.out.print(String.format(
					DEBUGMSG.getString("startgetSubtitle"), url, season,
					episode, lang.toString()));
		Set<Subtitle> subs = null;
		boolean tryagain;
		timer = 10000;
		do {
			tryagain = false;
			try {
				subs = BetaSerieApi.getSubtitles().show(url, lang, season,
						episode);
			} catch (BetaseriesApiException e) {
				tryagain = tryAgain(e);
			}
		} while (tryagain);
		if (Reglages.DEBUG)
			System.out.println(DEBUGMSG.getString("processComplete"));
		return subs;
	}

	public static synchronized void setWatched(Episode ep) {
		if (Reglages.DEBUG)
			System.out.print(String.format(
					DEBUGMSG.getString("startsetWatched"), ep.toString()));
		boolean tryagain;
		timer = 10000;
		do {
			tryagain = false;
			try {
				BetaSerieApi.getMembers().setWatched(Reglages.getToken(),
						ep.getShowUrl(), ep.getSeason(), ep.getEpisode());
			} catch (BetaseriesApiException e) {
				tryagain = tryAgain(e);
			}
		} while (tryagain);
		// TODO test retour
		if (Reglages.DEBUG)
			System.out.println(DEBUGMSG.getString("processComplete"));
	}

	public static void setArchived(Show show, boolean b) {
		if (Reglages.DEBUG)
			if (b)
				System.out
						.print(String.format(
								DEBUGMSG.getString("startsetArchived"),
								show.toString()));
			else
				System.out.print(String.format(
						DEBUGMSG.getString("startsetArchived2"),
						show.toString()));

		boolean tryagain;
		timer = 10000;
		do {
			tryagain = false;
			try {
				if (b)
					BetaSerieApi.getShows().archive(Reglages.getToken(),
							show.getUrl());
				else
					BetaSerieApi.getShows().unarchive(Reglages.getToken(),
							show.getUrl());
			} catch (BetaseriesApiException e) {
				tryagain = tryAgain(e);
			}
		} while (tryagain);
		// TODO test retour
		if (Reglages.DEBUG)
			System.out.println(DEBUGMSG.getString("processComplete"));

	}

	public static Episode scrapeFile(Path file) {
		if (Reglages.DEBUG)
			System.out.print(String.format(
					DEBUGMSG.getString("startScrapeFile"), file.toString()));
		Episode ep = null;
		boolean tryagain;
		timer = 10000;
		do {
			tryagain = false;
			try {
				ep = BetaSerieApi.getShows().scraper(file.toString());
			} catch (BetaseriesApiException e) {
				tryagain = tryAgain(e);
			}
		} while (tryagain);
		if (Reglages.DEBUG)
			System.out.println(DEBUGMSG.getString("processComplete"));
		return ep;

	}

}
